home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 7 / Example 7.1 / skinnedMesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-12  |  4.9 KB  |  162 lines

  1. #include "skinnedMesh.h"
  2.  
  3. class BONE_HIERARCHY: public ID3DXAllocateHierarchy
  4. {
  5.     public:
  6.         STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);
  7.         STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);
  8.         STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
  9.         STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
  10. };
  11.  
  12. HRESULT BONE_HIERARCHY::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
  13. {
  14.     BONE *newBone = new BONE;
  15.     memset(newBone, 0, sizeof(BONE));
  16.  
  17.     //Copy name
  18.     if(Name != NULL)
  19.     {
  20.         newBone->Name = new char[strlen(Name)+1];
  21.         strcpy(newBone->Name, Name);
  22.     }
  23.  
  24.     //Set the transformation matrices
  25.     D3DXMatrixIdentity(&newBone->TransformationMatrix);
  26.     D3DXMatrixIdentity(&newBone->CombinedTransformationMatrix);
  27.  
  28.     //Return the new bone...
  29.     *ppNewFrame = (D3DXFRAME*)newBone;
  30.  
  31.     return S_OK;
  32. }
  33.  
  34. HRESULT BONE_HIERARCHY::CreateMeshContainer(LPCSTR Name,
  35.                                             CONST D3DXMESHDATA *pMeshData,
  36.                                             CONST D3DXMATERIAL *pMaterials,
  37.                                             CONST D3DXEFFECTINSTANCE *pEffectInstances,
  38.                                             DWORD NumMaterials,
  39.                                             CONST DWORD *pAdjacency,
  40.                                             LPD3DXSKININFO pSkinInfo,
  41.                                             LPD3DXMESHCONTAINER *ppNewMeshContainer)
  42. {
  43.     //Just return a temporary mesh for now...
  44.     *ppNewMeshContainer = new BONEMESH;
  45.     memset(*ppNewMeshContainer, 0, sizeof(BONEMESH));
  46.  
  47.     return S_OK;
  48. }
  49.  
  50. HRESULT BONE_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree) 
  51. {
  52.     if(pFrameToFree)
  53.     {
  54.         if(pFrameToFree->Name != NULL)
  55.             delete [] pFrameToFree->Name;
  56.         delete pFrameToFree;
  57.     }
  58.     pFrameToFree = NULL;
  59.  
  60.     return S_OK; 
  61. }
  62.  
  63. HRESULT BONE_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
  64. {
  65.     if(pMeshContainerBase != NULL)
  66.         delete pMeshContainerBase;
  67.  
  68.     return S_OK;
  69. }
  70.  
  71.  
  72. //////////////////////////////////////////////////////////////////////////////////////////////////
  73. //                                    SKINNED MESH                                                //
  74. //////////////////////////////////////////////////////////////////////////////////////////////////
  75.  
  76. struct VERTEX{
  77.     VERTEX();
  78.     VERTEX(D3DXVECTOR3 pos, D3DCOLOR col){position = pos; color = col;}
  79.     D3DXVECTOR3 position;
  80.     D3DCOLOR color;
  81.     static const DWORD FVF;
  82. };
  83.  
  84. const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
  85.  
  86. SKINNEDMESH::SKINNEDMESH()
  87. {
  88.     m_pRootBone = NULL;
  89.     m_pSphereMesh = NULL;
  90. }
  91.  
  92. SKINNEDMESH::~SKINNEDMESH()
  93. {
  94.     BONE_HIERARCHY boneHierarchy;
  95.     boneHierarchy.DestroyFrame(m_pRootBone);
  96. }
  97.  
  98. void SKINNEDMESH::Load(char fileName[], IDirect3DDevice9 *Dev)
  99. {
  100.     m_pDevice = Dev;
  101.  
  102.     BONE_HIERARCHY boneHierarchy;
  103.  
  104.     D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED, m_pDevice, &boneHierarchy,
  105.                                NULL, &m_pRootBone, NULL);
  106.  
  107.     D3DXMATRIX i;
  108.     UpdateMatrices((BONE*)m_pRootBone, D3DXMatrixIdentity(&i));
  109.  
  110.     //Create Sphere
  111.     D3DXCreateSphere(m_pDevice, 0.07f, 10, 10, &m_pSphereMesh, NULL);
  112. }
  113.  
  114. void SKINNEDMESH::UpdateMatrices(BONE* bone, D3DXMATRIX *parentMatrix)
  115. {
  116.     if(bone == NULL)return;
  117.  
  118.     D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
  119.                        &bone->TransformationMatrix,
  120.                        parentMatrix);
  121.  
  122.     if(bone->pFrameSibling)UpdateMatrices((BONE*)bone->pFrameSibling, parentMatrix);
  123.     if(bone->pFrameFirstChild)UpdateMatrices((BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
  124. }
  125.  
  126. void SKINNEDMESH::RenderSkeleton(BONE* bone, BONE *parent, D3DXMATRIX world)
  127. {
  128.     //Temporary function to render the bony hierarchy
  129.     if(world == NULL)return;
  130.     if(bone == NULL)bone = (BONE*)m_pRootBone;
  131.  
  132.     D3DXMATRIX r, s;
  133.     D3DXMatrixRotationYawPitchRoll(&r, -D3DX_PI * 0.5f, 0.0f, 0.0f);
  134.  
  135.     //Draw Sphere
  136.     m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
  137.     m_pDevice->SetTransform(D3DTS_WORLD, &(r * bone->CombinedTransformationMatrix * world));
  138.     if(bone->Name != NULL)m_pSphereMesh->DrawSubset(0);
  139.  
  140.     //Draw line between bones
  141.     if(parent != NULL && bone->Name != NULL && parent->Name != NULL)
  142.     {
  143.         D3DXMATRIX w1 = bone->CombinedTransformationMatrix;
  144.         D3DXMATRIX w2 = parent->CombinedTransformationMatrix;
  145.  
  146.         //Extract translation
  147.         D3DXVECTOR3 thisBone = D3DXVECTOR3(w1(3, 0), w1(3, 1), w1(3, 2));
  148.         D3DXVECTOR3 ParentBone = D3DXVECTOR3(w2(3, 0), w2(3, 1), w2(3, 2));
  149.  
  150.         if(D3DXVec3Length(&(thisBone - ParentBone)) < 2.0f)
  151.         {
  152.             m_pDevice->SetTransform(D3DTS_WORLD, &world);
  153.             VERTEX vert[] = {VERTEX(ParentBone, 0xffff0000), VERTEX(thisBone, 0xff00ff00)};
  154.             m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  155.             m_pDevice->SetFVF(VERTEX::FVF);
  156.             m_pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 1, &vert[0], sizeof(VERTEX));
  157.         }
  158.     }
  159.  
  160.     if(bone->pFrameSibling)RenderSkeleton((BONE*)bone->pFrameSibling, parent, world);
  161.     if(bone->pFrameFirstChild)RenderSkeleton((BONE*)bone->pFrameFirstChild, bone, world);
  162. }